//
//  DYNetworkDelegate.m
//  Pods
//
//  Created by LXF on 16/6/30.
//
//

#import "DYNetworkDelegate.h"
#import "CustomLogTools.h"
#import "Foundation_category.h"
#import "NSString+DY_EncryptionTools.h"
#import "NSDictionary+DY_EncryptionTools.h"
#import "UIKit_Category.h"
#import "XXError.h"
#import "BaseModelProxy.h"
#import "BaseModel.h"
#import "YYModel.h"
#import "DYAccountProxy.h"

#import "DYLibraryConfig.h"

@implementation DYNetworkDelegate

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.keyPathNeedful = YES;
    }
    return self;
}

-(DYAccountProxy *)accountProxy{
    if (_accountProxy == nil) {
        return [DYAccountProxy isLogged];
    }
    return _accountProxy;
}

-(instancetype)encryption1WithKeyByPassword{
    [self setProcessParames:^(NSDictionary *__autoreleasing *parames, NSString *dateStamp, NSError *__autoreleasing *serializationError, id mark) {
        *parames = [*parames dy_encryption1];
    }];
    return self;
}
-(instancetype)encryption2WithKeyByPassword{
    [self setProcessParames:^(NSDictionary *__autoreleasing *parames, NSString *dateStamp, NSError *__autoreleasing *serializationError, id mark) {
        *parames = [*parames dy_encryption2_1ByDate:dateStamp];
    }];
    return self;
}

-(instancetype)encryption1WithKeys:(NSArray *)keys{
    [self setProcessParames:^(NSDictionary *__autoreleasing *parames, NSString *dateStamp, NSError *__autoreleasing *serializationError, id mark) {
        *parames = [*parames dy_encryption1WithKeys:keys];
    }];
    return self;
}
-(instancetype)encryption2WithKeys:(NSArray *)keys{
    [self setProcessParames:^(NSDictionary *__autoreleasing *parames, NSString *dateStamp, NSError *__autoreleasing *serializationError, id mark) {
        *parames = [*parames dy_encryption2_1ByDate:dateStamp keys:keys];
    }];
    return self;
}

-(instancetype)autoTo:(Class)clazz keyPath:(NSString *)keyPath{
    return [self autoTo:clazz keys:[keyPath componentsSeparatedByString:@"."]];
}
- (void)setDefaultParseResponseWithKeys:(NSArray<NSString *> *)keys {
    [self setParseResponsByTargetData:^id(id res, NSError *__autoreleasing *serializationError, id mark) {
        
        for (NSString *key in keys) {
            res = [res objectForKey:key];
        }
        if (res == nil && self.keyPathNeedful) {
            *serializationError = [XXDataError errorWithMark:CodeInfo];
            printE(@"服务器数据异常..");
        }
        return res;
    }];
}

-(instancetype)autoTo:(Class)clazz keys:(NSArray<NSString *> *)keys{
    
    [self setDefaultParseResponseWithKeys:keys];
    
    [self setParseTargetDataToTarget:^id(id res, NSError *__autoreleasing *serializationError, id mark) {
        
        if (clazz == nil || (res == nil && self.keyPathNeedful == NO)) {
            printW(@"不需要自动转换target的的请求,,%@",res);
            return res;
        }
        
        BOOL isDict;
        
        if ([res isKindOfClass:[NSDictionary class]]) {
            isDict = YES;
        }else if([res isKindOfClass:[NSArray class]]){
            isDict = NO;
        }else{
            *serializationError = [XXDataError errorWithMark:CodeInfo];
            printE(@"服务器数据异常..target 不是字典 也不是数组 %@",res);
            return res;
        }
        
        if ([clazz isSubclassOfClass:[BaseModel class]]) {
            
            res = isDict ? [clazz modelWithDict:res] : [clazz modelsWithDicts:res];
            
        }else if ([clazz isSubclassOfClass:[BaseModelProxy class]]){
            res = isDict ? [clazz mpWithModelDict:res] : [clazz mpsWithDicts:res];
        }else{
            if (isDict) {
                id any = [[clazz alloc]init];
                [any setValuesForKeysWithDictionary:res];
                res = any;
            }else{
                NSMutableArray *arrayM = [NSMutableArray array];
                for (NSDictionary *dict in res) {
                    id any = [[clazz alloc]init];
                    [any setValuesForKeysWithDictionary:dict];
                    //#warning test autoToAnyList
                    //                [any setValuesForKeysWithDictionary:res];
                    [arrayM addObject:any];
                }
                res = arrayM.copy;
            }
        }
        
        return res;
    }];
    return self;
}



-(instancetype)autoToAny:(Class)clazz keyPath:(NSString *)keyPath{
    return [self autoToAny:clazz keys:[keyPath componentsSeparatedByString:@"."]];
}
-(instancetype)autoToAnyList:(Class)clazz keyPath:(NSString *)keyPath{
    return [self autoToAnyList:clazz keys:[keyPath componentsSeparatedByString:@"."]];
}

-(instancetype)autoToAny:(Class)clazz keys:(NSArray<NSString *> *)keys{
    
    [self setDefaultParseResponseWithKeys:keys];
    
    [self setParseTargetDataToTarget:^id(id res, NSError *__autoreleasing *serializationError, id mark) {
        
        if (clazz == nil) {
            printW(@"不需要自动转换target的的请求,,%@",res);
            return res;
        }
        
        if ([res isKindOfClass:[NSDictionary class]] == NO) {
            *serializationError = [XXDataError errorWithMark:CodeInfo];
            printE(@"服务器数据异常..target 不是字典 %@",res);
            return res;
        }
        
        if ([clazz isSubclassOfClass:[BaseModel class]]) {
            res = [clazz modelWithDict:res];
        }else if ([clazz isSubclassOfClass:[BaseModelProxy class]]){
            res = [clazz mpWithModelDict:res];
        }else{
            id any = [[clazz alloc]init];
            [any setValuesForKeysWithDictionary:res];
            res = any;
        }
        return res;
    }];
    return self;
}
-(instancetype)autoToAnyList:(Class)clazz keys:(NSArray<NSString *> *)keys{
    
    [self setDefaultParseResponseWithKeys:keys];
    
    [self setParseTargetDataToTarget:^id(id res, NSError *__autoreleasing *serializationError, id mark) {
        
        if (clazz == nil && [res isKindOfClass:[NSArray class]] == YES) {
            printW(@"不需要自动转换 targetList 的的请求,,%@",res);
            return res;
        }
        
        if ([res isKindOfClass:[NSArray class]] == NO) {
             *serializationError = [XXDataError errorWithMark:CodeInfo];
            printE(@"服务器数据异常..");
            return res;
        }
        
        if ([clazz isSubclassOfClass:[BaseModel class]]) {
            res = [clazz modelsWithDicts:res];
        }else if ([clazz isSubclassOfClass:[BaseModelProxy class]]){
            res = [clazz mpsWithDicts:res];
        }else{
            NSMutableArray *arrayM = [NSMutableArray array];
            for (NSDictionary *dict in res) {
                id any = [[clazz alloc]init];
                [any setValuesForKeysWithDictionary:dict];
//#warning test autoToAnyList
//                [any setValuesForKeysWithDictionary:res];
                [arrayM addObject:any];
            }
            res = arrayM.copy;
        }
        return res;
    }];
    return self;
}
//
//-(instancetype)autoToModelProxy:(Class)modelProxyClass path:(NSArray<NSString *> *)path{
//    __weak typeof(self) weakSelf = self;
//    [self setParseResponsByTargetData:^id(id res, NSError *__autoreleasing *serializationError, id mark) {
//        for (NSString *key in path) {
//            res = [res objectForKey:key];
//        }
//        if (res == nil) {
//            *serializationError = [XXDataError errorWithMark:CodeInfo];
//            printE(@"服务器数据异常..");
//        }
//        return res;
//    }];
//    [self setParseTargetDataToTarget:^id(id res, NSError *__autoreleasing *serializationError, id mark) {
//        if ([res isKindOfClass:[NSDictionary class]] == NO) {
//            *serializationError = [XXDataError errorWithMark:CodeInfo];
//            printE(@"服务器数据异常..");
//            return res;
//        }
//        [modelProxyClass mpWithModelDict:res];
//        return res;
//    }];
//}
//
//-(instancetype)autoToModelProxyList:(Class)modelProxyClass path:(NSArray<NSString *> *)path{
//    __weak typeof(self) weakSelf = self;
//    [self setParseResponsByTargetData:^id(id res, NSError *__autoreleasing *serializationError, id mark) {
//        for (NSString *key in path) {
//            res = [res objectForKey:key];
//        }
//        if (res == nil) {
//            *serializationError = [XXDataError errorWithMark:CodeInfo];
//            printE(@"服务器数据异常..");
//        }
//        return res;
//    }];
//    [self setParseTargetDataToTarget:^id(id res, NSError *__autoreleasing *serializationError, id mark) {
//        if ([res isKindOfClass:[NSArray class]] == NO) {
//            *serializationError = [XXDataError errorWithMark:CodeInfo];
//            printE(@"服务器数据异常..");
//            return res;
//        }
//        [modelProxyClass mpsWithDicts:res];
//        return res;
//    }];
//}

#pragma mark - 默认 block

///  获取Respons中的 data 数据并且返回
-(ParseResponsByTargetHandle)defaultParseResponsByTargetData{
    return (id)^(id res,NSError **serializationError,id mark){
        return [res objectForKey:@"data"];
    };
}

/// 解析 从 ParseResponsByTargetData 获取到的 targetData，默认不解析，原封不动返回
-(ParseResponsByTargetHandle)defaultParseTargetDataToTarget{
    return (id)^(id res,NSError **serializationError,id mark){
        return res;
    };
}

/// 处理参数的 block，可用于加密，最后需要 *parameter = dicr; 替换旧的参数
-(ProcessParamesHandle)defaultProcessParames{
    return ^(NSDictionary **parames,NSString *timeStamp,NSError **serializationError,id mark){
    };
}

/// 处理请求头
-(ProcessRequestHeaderHandle)defaultProcessRequestHeader{
    return ^(NSDictionary **parames,NSString *timeStamp,NSMutableURLRequest *request,NSError **serializationError,id mark){
        NSString *appVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleVersionKey];
        NSString *systemVersion = [UIDevice systemVersion];
        NSString *deviceID = [[UIDevice currentDevice].identifierForVendor UUIDString];
        NSString *uid = [NSString stringWithFormat:@"%zd",self.accountProxy.model.identifier];
        NSString *token = self.accountProxy.model.access_token;
        NSString *hmac = [NSString dy_generateHmacAuthCodeWithDeviceID:deviceID date:timeStamp userID:uid accesstoken:token];
        NSDictionary<NSString *,NSString *> *dict = @{
                                                      @"App-Name":[DYLibraryConfig shared].appName,//@"com.dyss.enery",
                                                      @"App-Version":appVersion,
                                                      @"System-Name":@"iOS",
                                                      @"System-Version":systemVersion,
                                                      @"Device-Identifier":deviceID,
                                                      @"Device-Time":timeStamp,
                                                      @"User-Id":uid,
                                                      @"Hmac":hmac
                                                      };
        [request setAllHTTPHeaderFields:dict];
    };
}

///  解析 response，如果 errcode != 0 错误
-(ParseResponsHandle)defaultParseResponse{
    return (id)^(id response,NSError **serializationError,id mark){
        if ([response isKindOfClass:[NSDictionary class]]) {
            if ([[response allKeys]containsObject:@"errcode"] == NO || [[response objectForKey:@"errcode"] integerValue] != 0) {
                NSString *str = @"服务器数据异常...";
                printE(@"服务器数据异常..%@",response);
                NSInteger code = -9999;
                if ([response objectForKey:@"errmsg"] != nil) {
                    str = [response objectForKey:@"errmsg"];
                }
                if ([[response allKeys]containsObject:@"errcode"]) {
                    code = [[response objectForKey:@"errcode"] integerValue];
                }
                code = code == 0 ? -9999 : code;
                *serializationError = [XXDataError errorWithShowMessage:NSLocalizedString(str, @"") code:code userInfo:@{}];
            }
            id target = response;
            if (*serializationError == nil) {
                id targetData = [self parseResponsByTargetData](response,serializationError,mark);
                if (*serializationError == nil) {
                    target = [self parseTargetDataToTarget](targetData,serializationError,mark);
                }
            }
            return target;
        }else{
            *serializationError = [XXError errorWithMark:CodeInfo];
        }
        return response;
    };
}


#pragma mark - 懒加载

-(ParseResponsByTargetHandle )parseResponsByTargetData{
    if (_parseResponsByTargetData == nil) {
        return [self defaultParseResponsByTargetData];
    }
    return _parseResponsByTargetData;
}

-(ParseResponsByTargetHandle )parseTargetDataToTarget{
    if (_parseTargetDataToTarget == nil) {
        return [self defaultParseTargetDataToTarget];
    }
    return _parseTargetDataToTarget;
}

@end
